#ifndef _HALMEM_T_H_
#define _HALMEM_T_H_

#include <hyper_t.h>
#include <spinlock_t.h>
#include <list_t.h>

#define DEV_TYPE_NOT                        0xFFFFFFFF
#define ADDRSPACE_NOT                       0
#define ADDRSPACE_IO                        1
#define ADDRSPACE_SDRAM                     2
#define ADDRSPACE_RAM                       3
#define ADDRSPACE_ROM                       4
#define ADDRSPACE_NORFLASH                  5
#define ADDRSPACE_NANDFLASH                 6

#define MAP_ONE_SIZE                        0x400000   /* 一个内存地址映射块 4M */

/* mmapdsc_t.flag[3:0] */

#define MAPFLAG_SZ_BIT                      0
#define MAPFLAG_SZ_16KB                     (1 << MAPFLAG_SZ_BIT)
#define MAPFLAG_SZ_32KB                     (2 << MAPFLAG_SZ_BIT)
#define MAPFLAG_SZ_4MB                      (8 << MAPFLAG_SZ_BIT)

/* mmapdsc_t.flag[7:4] */

#define MAPFLAG_ACSZ_BIT                    4
#define MAPFLAG_ACSZ_128KB                  (1 << MAPFLAG_ACSZ_BIT) /* 大内存分成 128KB */
#define MAPFLAG_ACSZ_256KB                  (2 << MAPFLAG_ACSZ_BIT) /* 大内存分成 256KB */
#define MAPFLAG_ACSZ_512KB                  (3 << MAPFLAG_ACSZ_BIT) /* 大内存分成 512KB */
#define MAPFLAG_ACSZ_1MB                    (4 << MAPFLAG_ACSZ_BIT) /* 大内存分成 1MB */
#define MAPFLAG_ACSZ_2MB                    (5 << MAPFLAG_ACSZ_BIT) /* 大内存分成 2MB */
#define MAPFLAG_ACSZ_4MB                    (6 << MAPFLAG_ACSZ_BIT) /* 大内存分成 4MB */

/* 构造 mmapdsc_t.flag 属性值 */

#define MAPFLAG_VAL(RESRV, ALLOCSZ, MSZ)    (RESRV | ALLOCSZ | MSZ)

/* mmapdsc_t.status 管理位状态 */

#define MEMSTA_BLK_UNOCCUPY                 0    /* 该小块未被占领 */
#define MEMSTA_BLK_OCCUPY                   1    /* 该小块已被占领 */

/* 内存块管理链表 (mmapdsc_t) 表示的内存块状态  */

#define MEMCLASS_FULL_FLAG                  1    /* 同类已经分配完 */
#define MEMCLASS_EMPT_FLAG                  2    /* 同类全部未分配 (空闲) */
#define MEMCLASS_FUEM_FLAG                  3    /* 同类部分分配 */


/* 固定大小内存块分类 (6种) */

#define PHYMEM_BLKSZ_HEAD_MAX               6

#define MEMCLS_128KB_INDEX                  0    /* 在分类数组里下标为 0 */
#define MEMCLS_256KB_INDEX                  1    /* 在分类数组里下标为 1 */
#define MEMCLS_512KB_INDEX                  2    /* 在分类数组里下标为 2 */
#define MEMCLS_1MB_INDEX                    3    /* 在分类数组里下标为 3 */
#define MEMCLS_2MB_INDEX                    4    /* 在分类数组里下标为 4 */
#define MEMCLS_4MB_INDEX                    5    /* 在分类数组里下标为 5 */

#define MEMBLK_128KB_SIZE                   0x20000
#define MEMBLK_256KB_SIZE                   0x40000
#define MEMBLK_512KB_SIZE                   0x80000
#define MEMBLK_1MB_SIZE                     0x100000
#define MEMBLK_2MB_SIZE                     0x200000
#define MEMBLK_4MB_SIZE                     0x400000

/* 内存管理标志位 */

#define MEMBLK_128KB_TOTBIT                 32
#define MEMBLK_256KB_TOTBIT                 16
#define MEMBLK_512KB_TOTBIT                 8
#define MEMBLK_1MB_TOTBIT                   4
#define MEMBLK_2MB_TOTBIT                   2
#define MEMBLK_4MB_TOTBIT                   1

#define MEMBLK_128KB_MASK                   0xFFFFFFFF      /* 1111 1111 1111 1111 1111 1111 1111 1111 */
#define MEMBLK_256KB_MASK                   0xFFFF          /* 1111 1111 1111 1111 */
#define MEMBLK_512KB_MASK                   0xFF            /* 1111 1111 */
#define MEMBLK_1MB_MASK                     0xF             /* 1111 */
#define MEMBLK_2MB_MASK                     0x3             /* 11 */
#define MEMBLK_4MB_MASK                     0x1             /* 1 */

typedef struct s_PHYADDRSPCE
    {
    u32_t     flag;        /* 地址空间的类型如 ADDRSPACE_IO, ADDRSPACE_SDRAM 等 */
    u32_t     devtype;     /* 根据地址空间的类型指定设备类型 */
    addr_t    addrstart;   /* 地址空间的物理开始地址 */
    addr_t    addrend;     /* 地址空间的物理结束地址 */
    } phyaddrspce_t;

/*
 * 一个内存管理单元抽象描述结构体, 它管理4MB大小的内存块,在实际分配时,它所描述的4MB
 * 可以被分割成128KB,256KB,512KB,1MB,2MB,4MB,只能分成同一大小的等份。
 *
 *      |  位段  |                            说明
 *      ------------------------------------------------------------------------
 *      | [31:8] | 预留                                                         
 *      ------------------------------------------------------------------------
 *      |        | 指示 mmapdsc_t 所表示的内存块的内部再次分为多大的小块 
 *      |        | 各值如下：
 *      |        |
 *      |        |  值  |         说明         |     <status> 域
 *      |        |------|---------------------|---------------------------------
 *      |        |   1  |把大内存的再分成      | [31:0]位,每个位对应小块的 
 *      |        |      |128KB小块,共32小块    |分配状态 (0表示空闲,1表示已分配)
 *      |        |------|---------------------|---------------------------------
 *      |        |   2  |把大内存的再分成      | [15:0]位,每个位对应小块的 
 *      |        |      |256KB小块, 共16小块   |分配状态 (0表示空闲,1表示已分配)
 *      |        |------|---------------------|---------------------------------
 *      | [7:4]  |   3  |把大内存的再分成      | [7:0]位,每个位对应小块的 
 *      |        |      |512KB小块,共 8小块    |分配状态 (0表示空闲,1表示已分配)
 *<flag>|        |------|---------------------|---------------------------------
 *      |        |   4  |把大内存的再分成      | [3:0]位,每个位对应小块的 
 *      |        |      |1MB小块,共4小块      |分配状态 (0表示空闲,1表示已分配)
 *      |        |------|---------------------|---------------------------------
 *      |        |   5  |把大内存的再分成      | [1:0]位,每个位对应小块的 
 *      |        |      |2MB小块,共2小块      |分配状态 (0表示空闲,1表示已分配)
 *      |        |------|---------------------|---------------------------------
 *      |        |   6  |把大内存的再分成      | [0]位,每个位对应小块的  
 *      |        |      |4MB小块,共4小块      |分配状态 (0表示空闲,1表示已分配)
 *      |--------|------|---------------------|---------------------------------
 *      |        | 指定 mmapdsc_t 所表示的内存块大小
 *      |        |  
 *      |        |  值  |                         说明
 *      |        |------|-------------------------------------------------------
 *      |        |   0  | 没有指定大小
 *      |        |------|-------------------------------------------------------
 *      |  [3:0] |   1  | 表示16KB大小的内存块
 *      |        |------|-------------------------------------------------------
 *      |        |   2  | 表示32KB大小的内存块
 *      |        |------|------------------------------------------------------- 
 *      |        |   8  | 表示4MB大小的内存块
 *      |--------|------|-------------------------------------------------------
 * 
 */

typedef struct s_MMAPDSC
    {
    spinlock_t lock;            /* 保护数据结构自身的自旋锁 */
    list_t     list;            /* 链表 */
    addr_t     phyaddrstart;    /* 该内存块物理开始地址 */
    addr_t     phyaddrend;      /* 该内存块物理结束地址 */
    u32_t      status;          /* 内存小块状态 */
    u32_t      flag;            /* 内存划分标志位 */
    } mmapdsc_t;

/*  
 * mmapdsc_t 结构容器
 * 用于挂载 同一种内存块大小的 mmapdsc_t 结构体 (不同状态: 完全分配, 未分配, 部分未分配)
 */

typedef struct s_MMCLASSLST
    {
    spinlock_t lock;            /* 保护数据结构自身的自旋锁 */
    size_t     size;            /* 该类大小 (字节) */
    list_t     fulllist;        /* 同类已经分配完的 mmapdsc_t 结构链表头 */
    list_t     emptylist;       /* 同类全部未分配(空闲)的 mmapdsc_t 结构链表头 */
    list_t     fuemlist;        /* 同类部分分配的 mmapdsc_t 结构链表头 */    
    } mmclasslst_t;

/*  
 * 128KB ~ 4MB 大小的 mmclasslst_t 队列数组
 * [0] 128KB, [1] 256kb, [2] 512kb, [3] 1MB, [4] 2MB, [5] 4MB
 */

typedef struct s_PHYMEM
    {
    spinlock_t   lock;            /* 保护数据结构自身的自旋锁 */
    list_t       list;
    uint_t       freeblks;
    uint_t       allcblks;
    mmclasslst_t classlist[PHYMEM_BLKSZ_HEAD_MAX];    /* mmclasslst_t 数组 */
    } phymem_t;

#endif